<template>
  <div class="file-uploader">
    <el-upload
      class="upload-demo"
      :auto-upload="false"
      :show-file-list="false"
      :on-change="handleFileChange"
      :accept="accept"
      ref="uploadRef"
    >
      <el-button type="primary" class="upload-btn" :loading="uploading">
        <el-icon><Upload /></el-icon>
        <span>{{ buttonText }}</span>
      </el-button>
    </el-upload>
    
    <div v-if="fileName" class="file-info">
      <div class="file-name">
        <el-icon><Document /></el-icon>
        <span>{{ fileName }}</span>
      </div>
      <slot name="file-actions"></slot>
    </div>
    
    <div v-if="uploading" class="upload-progress">
      <el-progress 
        :percentage="uploadProgress" 
        :status="uploadStatus"
        :stroke-width="10"
        :show-text="true"
        :format="(percentage) => `${percentage}%`"
        :color="getProgressColor"
      />
      <div class="upload-status-text" v-if="uploadStatus === 'warning'">
        <el-icon><Loading /></el-icon>
        <span>服务器处理中...</span>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, defineEmits } from 'vue'
import { Upload, Document, Loading } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import axios from 'axios'

const props = defineProps({
  // 上传按钮文本
  buttonText: {
    type: String,
    default: '选择文件'
  },
  // 接受的文件类型
  accept: {
    type: String,
    default: '*/*'
  },
  // 上传的业务代码
  code: {
    type: Number,
    required: true
  }
})

const emit = defineEmits(['upload-success', 'upload-error', 'upload-progress'])

// 上传相关状态
const uploading = ref(false)
const uploadProgress = ref(0)
const uploadStatus = ref('')
const fileName = ref('')
const uploadRef = ref(null)

// 根据上传状态和进度动态计算进度条颜色
const getProgressColor = (percentage) => {
  if (uploadStatus.value === 'exception') return '#F56C6C' // 错误状态为红色
  if (uploadStatus.value === 'warning') return '#E6A23C' // 警告状态为橙色
  if (percentage < 30) return '#909399' // 初始阶段为灰色
  if (percentage < 80) return '#409EFF' // 中间阶段为蓝色
  return '#67C23A' // 接近完成为绿色
}

// 处理文件上传
const handleFileChange = async (file) => {
  if (!file) return
  
  uploading.value = true
  uploadProgress.value = 0
  uploadStatus.value = ''
  
  try {
    const formData = new FormData()
    formData.append('file', file.raw)
    
    const config = {
      url: `/api/file/upload/${props.code}`,
      method: 'post',
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      timeout: 300000, // 5分钟超时
      onUploadProgress: (progressEvent) => {
        // 计算上传进度百分比
        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        // 限制进度最大为99%，直到服务器响应成功后才显示100%
        uploadProgress.value = Math.min(percentCompleted, 99)
        emit('upload-progress', uploadProgress.value)
        
        // 当上传完成但还在处理时
        if (percentCompleted >= 99) {
          uploadStatus.value = 'warning' // 使用警告状态表示等待服务器处理
        }
      }
    }
    
    // 获取token并添加到请求头
    const token = localStorage.getItem('token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    
    // 使用axios直接发送请求，而不是通过封装的service
    // 这样可以直接使用onUploadProgress
    const response = await axios(config)
    
    if (response.status === 200 && response.data.code === 200) {
      // 上传成功后才将进度设为100%
      uploadProgress.value = 100
      uploadStatus.value = 'success'
      fileName.value = response.data.data.split('/').pop() // 从URL中提取文件名
      
      emit('upload-success', {
        fileName: fileName.value,
        fileUrl: response.data.data,
        file: file.raw
      })
      
      ElMessage.success('上传成功')
    } else {
      uploadStatus.value = 'exception'
      emit('upload-error', response.data.msg || '上传失败')
      ElMessage.error(response.data.msg || '上传失败')
    }
  } catch (error) {
    console.error('文件上传出错:', error)
    uploadStatus.value = 'exception'
    // 上传失败时保持进度条在当前值，不要自动变为100%
    uploadProgress.value = Math.min(uploadProgress.value, 99)
    emit('upload-error', error.message || '上传失败，请稍后重试')
    ElMessage.error(error.message || '上传失败，请稍后重试')
  } finally {
    // 上传完成后，延迟一段时间再隐藏进度条，让用户有时间看到结果
    setTimeout(() => {
      if (uploadStatus.value === 'success') {
        uploading.value = false
      }
    }, 1500)
  }
}

// 重置上传组件
const resetUploader = () => {
  fileName.value = ''
  uploadProgress.value = 0
  uploading.value = false
  uploadStatus.value = ''
  if (uploadRef.value) {
    uploadRef.value.clearFiles()
  }
}

// 暴露方法给父组件
defineExpose({
  resetUploader
})
</script>

<style scoped>
.file-uploader {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.upload-btn {
  display: flex;
  align-items: center;
  gap: 5px;
}

.file-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 8px;
}

.file-name {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 14px;
  color: #606266;
  word-break: break-all;
}

.upload-progress {
  margin-top: 8px;
}

.upload-status-text {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 5px;
  font-size: 12px;
  color: #E6A23C;
}
</style>